<!DOCTYPE html>
<html lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  
  <title itemprop="name">9种设计模式在Spring中的运用，一定要非常熟练！ | 耿超Blog</title>
  
    <link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/28.jpg">
  
  <meta http-equiv="x-dns-prefetch-control" content="on">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+SerifMerriweather|Merriweather+Sans|Source+Code+Pro|Ubuntu:400,700|Noto+Serif+SC" media="all">
  <link rel="dns-prefetch" href="//cdn.jsdelivr.net">
  <link rel="stylesheet" id="saukra_css-css" href="/css/style.css" type="text/css" media="all">


  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.6/dist/jquery.fancybox.min.css">

  <link rel="stylesheet" href="/css/lib.min.css" media="all">
  <link rel="stylesheet" href="/css/font.css" media="all">
  <link rel="stylesheet" href="/css/insight.css" media="all">
  <link rel="stylesheet" href="/css/jquery.fancybox.min.css" media="all">
  <link rel="stylesheet" href="/css/zoom.css" media="all">
  <link rel="stylesheet" type="text/css" href="/css/sharejs.css">
<!--   <link rel="stylesheet" id="saukra_css-css" href="https://2heng.xin/wp-content/cache/autoptimize/css/autoptimize_ad42a61f4c7d4bdd9f91afcff6b5dda5.css
" type="text/css" media="all"> -->
  <script>
  /*Initial Variables*/
  var mashiro_option = new Object();
  var mashiro_global = new Object();
  mashiro_option.NProgressON = true;
  /* 
   * 邮箱信息之类的东西可以填在这里，这些js变量基本都作用于sakura-app.js
   * 这样的设置仅是为了方便在基于PHP开发的主题中设置js变量，既然移植到了Node上，我想或许可以精简这一逻辑吧
   */
  mashiro_option.email_domain = "";
  mashiro_option.email_name = "";
  mashiro_option.cookie_version_control = "";
  mashiro_option.qzone_autocomplete = false;
  mashiro_option.site_name = "BigBoss耿超";
  mashiro_option.author_name = "耿超";
  mashiro_option.site_url = "https://www.gengchao.vip";
  mashiro_option.v_appId = "aeY1WNVHlNPxnev04uP4OGiN-gzGzoHsz";
  mashiro_option.v_appKey = "eC65yOIwHWdj1SI18Dc25mV2";
  mashiro_option.mathjax = "0";
  mashiro_option.qq_api_url = "https://api.mashiro.top/qqinfo/"; 
  mashiro_option.qq_avatar_api_url = "https://api.mashiro.top/qqinfo/";

  // mashiro_option.jsdelivr_css_src = "https://cdn.jsdelivr.net/gh/moezx/cdn@3.4.5/css/lib.min.css";
  // mashiro_option.float_player_on = true;

  /*End of Initial Variables*/
  </script>
  <script type="text/javascript">
  var bg = "https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/3.jpg,https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/9.jpg,https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/10.jpg".split(",");
  var bgindex = Math.floor(Math.random()*bg.length);
  if (!!window.ActiveXObject || "ActiveXObject" in window) { //is IE?
    alert('朋友，IE浏览器未适配哦~');
  }
  </script>
  <style type="text/css">
  .hljs-ln{border-collapse:collapse}.hljs-ln td{padding:0}.hljs-ln-n:before{content:attr(data-line-number)}
  </style>
  <style type="text/css">.site-top .lower nav{display:block !important;}.author-profile i,.post-like a,.post-share .show-share,.sub-text,.we-info a,span.sitename,.post-more i:hover,#pagination a:hover,.post-content a:hover,.float-content i:hover{color:#FE9600}.feature i,.download,.navigator i:hover,.links ul li:before,.ar-time i,span.ar-circle,.object,.comment .comment-reply-link,.siren-checkbox-radio:checked + .siren-checkbox-radioInput:after{background:#FE9600}::-webkit-scrollbar-thumb{background:#FE9600}.download,.navigator i:hover,.link-title,.links ul li:hover,#pagination a:hover,.comment-respond input[type='submit']:hover{border-color:#FE9600}.entry-content a:hover,.site-info a:hover,.comment h4 a,#comments-navi a.prev,#comments-navi a.next,.comment h4 a:hover,.site-top ul li a:hover,.entry-title a:hover,#archives-temp h3,span.page-numbers.current,.sorry li a:hover,.site-title a:hover,i.iconfont.js-toggle-search.iconsearch:hover,.comment-respond input[type='submit']:hover{color:#FE9600}.comments .comments-main{display:block !important;}.comments .comments-hidden{display:none !important;}background-position:center center;background-attachment:inherit;}
  </style>
</head>
</html>
<body class="page-template page-template-user page-template-page-analytics page-template-userpage-analytics-php page page-id-1297 chinese-font serif isWebKit">
  <div class="scrollbar" id="bar">
  </div>
  <a href="#" class="cd-top faa-float animated"></a>
  <section id="main-container">
    <div class="headertop filter-dim">
  <div id="banner_wave_1"></div>
  <div id="banner_wave_2"></div>
  <figure id="centerbg" class="centerbg">
    <div class="focusinfo no-select">
     <!-- <div class="header-tou">
        <a href="https://www.gengchao.vip">
          <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/21.jpg">
        </a>
      </div>-->
      <div class="header-info">
        <p>虽千万人，吾往矣！！</p>
        <div class="top-social_v2">
          <li id="bg-pre">
            <img class="flipx" src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/next-b.svg">
          </li>
          
            
              
                <li>
                  <a href="http://github.com/geng-chao" target="_blank" class="social-github" title="github">
                    <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/social/github.png">
                  </a>
                </li>
              
            
              
                <li>
                  <a href="https://y.qq.com/portal/profile.html#stat=y_new.top.user_pic" target="_blank" class="social-github" title="wangyiyun">
                    <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/social/wangyiyun.png">
                  </a>
                </li>
              
            
              
                <li>
                  <a href="http://weibo.com/mashirozx?is_all=1" target="_blank" class="social-github" title="email">
                    <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/social/email.svg">
                  </a>
                </li>
              
            
              
                <li class="wechat">
                  <a href="/#">
                    <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/social/wechat.png">
                  </a>
                  <div class="wechatInner">
                    <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/31.jpg">
                  </div>
                </li>
              
            
          
          <li id="bg-next">
            <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/next-b.svg">
          </li>
        </div>
      </div>
    </div>
  </figure>
  <div id="video-container" style="">
    <video style="object-fit: fill" id="bgvideo" class="video" video-name="" src="" width="auto" preload="auto">
    </video>
    <div id="video-btn" class="loadvideo videolive">
    </div>
    <div id="video-add">
    </div>
    <div class="video-stu">
    </div>
  </div>
  <div class="headertop-down faa-float animated" onclick="headertop_down()">
    <span>
      <i class="fa fa-chevron-down" aria-hidden="true">
      </i>
    </span>
  </div>
</div>
    <div id="page" class="site wrapper">
      <header class="site-header no-select gizle sabit" role="banner">
  <div class="site-top">
    <div class="site-branding">
      <span class="site-title">
        <span class="logolink moe-mashiro">
          <a href="/">
            <span class="sakurasono">BigBoss</span>
            <span class="shironeko">耿超</span>
          </a>
        </span>
      </span>
    </div>
    <div class="searchbox search-form-submit">
      <i class="iconfont js-toggle-search iconsearch icon-search">
      </i>
    </div>
    <div id="show-nav" class="showNav mobile-fit">
      <div class="line line1">
      </div>
      <div class="line line2">
      </div>
      <div class="line line3">
      </div>
    </div>
    <div class="lower-cantiner">
      <div class="lower">
        <nav class="mobile-fit-control hide">
          <ul id="menu-new" class="menu">
            
              <li>
                <a href="/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-fort-awesome faa-shake" aria-hidden="true"></i>
                    首页
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/archives">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-archive faa-shake" aria-hidden="true"></i>
                    归档
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/categories/技术/">
                          <i class="fa fa-code" aria-hidden="true"></i>
                          技术
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/生活/">
                          <i class="fa fa-file-text-o" aria-hidden="true"></i>
                          生活
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/资源/">
                          <i class="fa fa-cloud-download" aria-hidden="true"></i>
                          资源
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/java/">
                          <i class="fa fa-commenting-o" aria-hidden="true"></i>
                          java
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/转载/">
                          <i class="fa fa-book" aria-hidden="true"></i>
                          转载
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="javascript:;">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-list-ul faa-vertical" aria-hidden="true"></i>
                    清单
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/tags/悦读/">
                          <i class="fa fa-th-list faa-bounce" aria-hidden="true"></i>
                          书单
                        </a>
                      </li>
                    
                      <li>
                        <a href="/bangumi/">
                          <i class="fa fa-film faa-vertical" aria-hidden="true"></i>
                          番组
                        </a>
                      </li>
                    
                      <li>
                        <a href="/music/">
                          <i class="fa fa-headphones" aria-hidden="true"></i>
                          歌单
                        </a>
                      </li>
                    
                      <li>
                        <a href="/tags/图集/">
                          <i class="fa fa-photo" aria-hidden="true"></i>
                          图集
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/comment/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-pencil-square-o faa-tada" aria-hidden="true"></i>
                    留言板
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/links/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
                    友人帐
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/donate/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-heart faa-pulse" aria-hidden="true"></i>
                    赞赏
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-leaf faa-wrench" aria-hidden="true"></i>
                    关于
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/about/">
                          <i class="fa fa-meetup" aria-hidden="true"></i>
                          我？
                        </a>
                      </li>
                    
                      <li>
                        <a href="/theme-sakura/">
                          <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                          主题
                        </a>
                      </li>
                    
                      <li>
                        <a href="/lab/">
                          <i class="fa fa-cogs" aria-hidden="true"></i>
                          Lab
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/client/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-android faa-vertical" aria-hidden="true"></i>
                    客户端
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/atom.xml">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-rss faa-pulse" aria-hidden="true"></i>
                    RSS
                  </span>
                </a>
                
              </li>
            
          </ul>
        </nav>
      </div>
    </div>
  </div>
</header>

      <link rel="stylesheet" type="text/css" href="/css/sharejs.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css">
<div class="pattern-center-blank"></div>

  <div class="pattern-center single-center">
    <!-- 有配图默认渲染第一张 -->
    <div class="pattern-attachment-img lazyload" style="background-image: url(https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/20200311153123.png);" src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/loader/orange.progress-bar-stripe-loader.svg" data-src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/20200311153123.png">
    </div>
    <header class="pattern-header single-header">
      <h1 class="entry-title">
      9种设计模式在Spring中的运用，一定要非常熟练！</h1>
      <p class="entry-census">
        <span>
          <a href="www.gcweb.top">
            <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/21.jpg">
          </a>
        </span>
        <span>
          <a href="www.gcweb.top">耿超</a>
        </span>
        <span class="bull">
        ·</span>
        2020-3-11<span class="bull">
        ·</span>
      <span id="busuanzi_value_page_pv"></span>次阅读</p>
    </header>
  </div>

<div id="content" class="site-content">
  <div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
      <article id="post-1" class="post-1 post type-post status-publish format-standard has-post-thumbnail hentry category-uncategorized">
        <div class="toc"></div>
        <!--<div class="toc-entry-content"><!-- 套嵌目录使用（主要为了支援评论）-->
        
        <div class="entry-content">
          <p>Spring中涉及的设计模式总结</p>
<h2 id="1-简单工厂-非23种设计模式中的一种"><a href="#1-简单工厂-非23种设计模式中的一种" class="headerlink" title="1.简单工厂(非23种设计模式中的一种)"></a>1.简单工厂(非23种设计模式中的一种)</h2><h3 id="实现方式："><a href="#实现方式：" class="headerlink" title="实现方式："></a>实现方式：</h3><p>BeanFactory。Spring中的BeanFactory就是简单工厂模式的体现，根据传入一个唯一的标识来获得Bean对象，但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。</p>
<h3 id="实质："><a href="#实质：" class="headerlink" title="实质："></a>实质：</h3><p>由一个工厂类根据传入的参数，动态决定应该创建哪一个产品类。</p>
<h3 id="实现原理："><a href="#实现原理：" class="headerlink" title="实现原理："></a>实现原理：</h3><p><strong>bean容器的启动阶段：</strong></p>
<ul>
<li><p>读取bean的xml配置文件,将bean元素分别转换成一个BeanDefinition对象。</p>
</li>
<li><p>然后通过BeanDefinitionRegistry将这些bean注册到beanFactory中，保存在它的一个ConcurrentHashMap中。</p>
</li>
<li><p>将BeanDefinition注册到了beanFactory之后，在这里Spring为我们提供了一个扩展的切口，允许我们通过实现接口BeanFactoryPostProcessor 在此处来插入我们定义的代码。</p>
<p>典型的例子就是：PropertyPlaceholderConfigurer，我们一般在配置数据库的dataSource时使用到的占位符的值，就是它注入进去的。</p>
</li>
</ul>
<p><strong>容器中bean的实例化阶段：</strong></p>
<p>实例化阶段主要是通过反射或者CGLIB对bean进行实例化，在这个阶段Spring又给我们暴露了很多的扩展点：</p>
<ul>
<li><strong>各种的Aware接口</strong>，比如 BeanFactoryAware，对于实现了这些Aware接口的bean，在实例化bean时Spring会帮我们注入对应的BeanFactory的实例。</li>
<li><strong>BeanPostProcessor接口</strong>，实现了BeanPostProcessor接口的bean，在实例化bean时Spring会帮我们调用接口中的方法。</li>
<li><strong>InitializingBean接口</strong>，实现了InitializingBean接口的bean，在实例化bean时Spring会帮我们调用接口中的方法。</li>
<li><strong>DisposableBean接口</strong>，实现了BeanPostProcessor接口的bean，在该bean死亡时Spring会帮我们调用接口中的方法。</li>
</ul>
<h3 id="设计意义："><a href="#设计意义：" class="headerlink" title="设计意义："></a>设计意义：</h3><p><strong>松耦合。</strong>可以将原来硬编码的依赖，通过Spring这个beanFactory这个工厂来注入依赖，也就是说原来只有依赖方和被依赖方，现在我们引入了第三方——spring这个beanFactory，由它来解决bean之间的依赖问题，达到了松耦合的效果.</p>
<p><strong>bean的额外处理。</strong>通过Spring接口的暴露，在实例化bean的阶段我们可以进行一些额外的处理，这些额外的处理只需要让bean实现对应的接口即可，那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。<code>[非常重要]</code></p>
<h2 id="2-工厂方法"><a href="#2-工厂方法" class="headerlink" title="2.工厂方法"></a>2.工厂方法</h2><h3 id="实现方式：-1"><a href="#实现方式：-1" class="headerlink" title="实现方式："></a>实现方式：</h3><p>FactoryBean接口。</p>
<h3 id="实现原理：-1"><a href="#实现原理：-1" class="headerlink" title="实现原理："></a>实现原理：</h3><p>实现了FactoryBean接口的bean是一类叫做factory的bean。其特点是，spring会在使用getBean()调用获得该bean时，会自动调用该bean的getObject()方法，所以返回的不是factory这个bean，而是这个bean.getOjbect()方法的返回值。</p>
<h4 id="例子："><a href="#例子：" class="headerlink" title="例子："></a>例子：</h4><p>典型的例子有spring与mybatis的结合。</p>
<p><strong>代码示例：</strong></p>
<p><img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/20200311153143.png" alt> </p>
<p><strong>说明：</strong></p>
<p>我们看上面该bean，因为实现了FactoryBean接口，所以返回的不是 SqlSessionFactoryBean 的实例，而是它的 SqlSessionFactoryBean.getObject() 的返回值。</p>
<h2 id="3-单例模式"><a href="#3-单例模式" class="headerlink" title="3.单例模式"></a>3.单例模式</h2><p>Spring依赖注入Bean实例默认是单例的。</p>
<p>Spring的依赖注入（包括lazy-init方式）都是发生在AbstractBeanFactory的getBean里。getBean的doGetBean方法调用getSingleton进行bean的创建。</p>
<p>分析getSingleton()方法</p>
<pre><code>public Object getSingleton(String beanName){
    //参数true设置标识允许早期依赖
    return getSingleton(beanName,true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //检查缓存中是否存在实例
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null &amp;&amp; isSingletonCurrentlyInCreation(beanName)) {
        //如果为空，则锁定全局变量并进行处理。
        synchronized (this.singletonObjects) {
            //如果此bean正在加载，则不处理
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null &amp;&amp; allowEarlyReference) {  
                //当某些方法需要提前初始化的时候则会调用addSingleFactory 方法将对应的ObjectFactory初始化策略存储在singletonFactories
                ObjectFactory&lt;?&gt; singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //调用预先设定的getObject方法
                    singletonObject = singletonFactory.getObject();
                    //记录在缓存中，earlysingletonObjects和singletonFactories互斥
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
</code></pre><p><strong>getSingleton()过程图</strong></p>
<p>ps：spring依赖注入时，使用了 双重判断加锁 的单例模式</p>
<p><img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/20200311153150.png" alt> </p>
<p><strong>总结</strong></p>
<p><strong>单例模式定义：</strong>保证一个类仅有一个实例，并提供一个访问它的全局访问点。</p>
<p><strong>spring对单例的实现：</strong>spring中的单例模式完成了后半句话，即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例，这是因为spring管理的是任意的java对象。</p>
<h2 id="4-适配器模式"><a href="#4-适配器模式" class="headerlink" title="4.适配器模式"></a>4.适配器模式</h2><h3 id="实现方式：-2"><a href="#实现方式：-2" class="headerlink" title="实现方式："></a>实现方式：</h3><p>SpringMVC中的适配器HandlerAdatper。</p>
<h3 id="实现原理：-2"><a href="#实现原理：-2" class="headerlink" title="实现原理："></a>实现原理：</h3><p>HandlerAdatper根据Handler规则执行不同的Handler。</p>
<h3 id="实现过程："><a href="#实现过程：" class="headerlink" title="实现过程："></a>实现过程：</h3><p>DispatcherServlet根据HandlerMapping返回的handler，向HandlerAdatper发起请求，处理Handler。</p>
<p>HandlerAdapter根据规则找到对应的Handler并让其执行，执行完毕后Handler会向HandlerAdapter返回一个ModelAndView，最后由HandlerAdapter向DispatchServelet返回一个ModelAndView。</p>
<h3 id="实现意义："><a href="#实现意义：" class="headerlink" title="实现意义："></a>实现意义：</h3><p>HandlerAdatper使得Handler的扩展变得容易，只需要增加一个新的Handler和一个对应的HandlerAdapter即可。</p>
<p>因此Spring定义了一个适配接口，使得每一种Controller有一种对应的适配器实现类，让适配器代替controller执行相应的方法。这样在扩展Controller时，只需要增加一个适配器类就完成了SpringMVC的扩展了。</p>
<h2 id="5-装饰器模式"><a href="#5-装饰器模式" class="headerlink" title="5.装饰器模式"></a>5.装饰器模式</h2><h3 id="实现方式：-3"><a href="#实现方式：-3" class="headerlink" title="实现方式："></a>实现方式：</h3><p>Spring中用到的包装器模式在类名上有两种表现：一种是类名中含有Wrapper，另一种是类名中含有Decorator。</p>
<h3 id="实质：-1"><a href="#实质：-1" class="headerlink" title="实质："></a>实质：</h3><p>动态地给一个对象添加一些额外的职责。</p>
<p>就增加功能来说，Decorator模式相比生成子类更为灵活。</p>
<p>扩展：<a href="http://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&amp;mid=2247486377&amp;idx=2&amp;sn=e88370d32c36b19ac89189341cbaf03b&amp;chksm=ebd63485dca1bd93fd46ce901b8ed5adaa0f1f5db15b8a19902bef66a05bd38ed420e26f7f5e&amp;scene=21#wechat_redirect" target="_blank" rel="noopener">设计模式是什么鬼（装饰）</a></p>
<h2 id="6-代理模式"><a href="#6-代理模式" class="headerlink" title="6.代理模式"></a>6.代理模式</h2><h3 id="实现方式：-4"><a href="#实现方式：-4" class="headerlink" title="实现方式："></a>实现方式：</h3><p>AOP底层，就是动态代理模式的实现。</p>
<h3 id="动态代理："><a href="#动态代理：" class="headerlink" title="动态代理："></a>动态代理：</h3><p>在内存中构建的，不需要手动编写代理类</p>
<h3 id="静态代理："><a href="#静态代理：" class="headerlink" title="静态代理："></a>静态代理：</h3><p>需要手工编写代理类，代理类引用被代理对象。</p>
<h3 id="实现原理：-3"><a href="#实现原理：-3" class="headerlink" title="实现原理："></a>实现原理：</h3><p>切面在应用运行的时刻被织入。一般情况下，在织入切面时，AOP容器会为目标对象创建动态的创建一个代理对象。SpringAOP就是以这种方式织入切面的。</p>
<p>织入：把切面应用到目标对象并创建新的代理对象的过程。</p>
<p>扩展：<a href="http://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&amp;mid=2247487054&amp;idx=2&amp;sn=489695986c038525e25c017c217b72fb&amp;chksm=ebd63162dca1b874edcaa30680e1da4d3a02c9b0011cb5c60c22d2b9ebea9169022813810bd5&amp;scene=21#wechat_redirect" target="_blank" rel="noopener">设计模式是什么鬼（代理）</a></p>
<h2 id="7-观察者模式"><a href="#7-观察者模式" class="headerlink" title="7.观察者模式"></a>7.观察者模式</h2><h3 id="实现方式：-5"><a href="#实现方式：-5" class="headerlink" title="实现方式："></a>实现方式：</h3><p>spring的事件驱动模型使用的是 观察者模式 ，Spring中Observer模式常用的地方是listener的实现。</p>
<h3 id="具体实现："><a href="#具体实现：" class="headerlink" title="具体实现："></a>具体实现：</h3><p>事件机制的实现需要三个部分,事件源,事件,事件监听器</p>
<p>ApplicationEvent抽象类<code>[事件]</code></p>
<p>继承自jdk的EventObject,所有的事件都需要继承ApplicationEvent,并且通过构造器参数source得到事件源.</p>
<p>该类的实现类ApplicationContextEvent表示ApplicaitonContext的容器事件.</p>
<p>代码：</p>
<pre><code>public abstract class ApplicationEvent extends EventObject {
    private static final long serialVersionUID = 7099057708183571937L;
    private final long timestamp;
    public ApplicationEvent(Object source) {
    super(source);
    this.timestamp = System.currentTimeMillis();
    }
    public final long getTimestamp() {
        return this.timestamp;
    }
}
</code></pre><p>ApplicationListener接口<code>[事件监听器]</code></p>
<p>继承自jdk的EventListener,所有的监听器都要实现这个接口。</p>
<p>这个接口只有一个onApplicationEvent()方法,该方法接受一个ApplicationEvent或其子类对象作为参数,在方法体中,可以通过不同对Event类的判断来进行相应的处理。</p>
<p>当事件触发时所有的监听器都会收到消息。</p>
<p>代码：</p>
<pre><code>public interface ApplicationListener&lt;E extends ApplicationEvent&gt; extends EventListener {
     void onApplicationEvent(E event);
} 
</code></pre><p>ApplicationContext接口<code>[事件源]</code></p>
<p>ApplicationContext是spring中的全局容器，翻译过来是”应用上下文”。</p>
<p>实现了ApplicationEventPublisher接口。</p>
<h3 id="职责："><a href="#职责：" class="headerlink" title="职责："></a>职责：</h3><p>负责读取bean的配置文档,管理bean的加载,维护bean之间的依赖关系,可以说是负责bean的整个生命周期,再通俗一点就是我们平时所说的IOC容器。</p>
<p>代码：</p>
<pre><code>public interface ApplicationEventPublisher {
        void publishEvent(ApplicationEvent event);
}   

public void publishEvent(ApplicationEvent event) {
    Assert.notNull(event, &quot;Event must not be null&quot;);
    if (logger.isTraceEnabled()) {
         logger.trace(&quot;Publishing event in &quot; + getDisplayName() + &quot;: &quot; + event);
    }
    getApplicationEventMulticaster().multicastEvent(event);
    if (this.parent != null) {
    this.parent.publishEvent(event);
    }
}
</code></pre><p>ApplicationEventMulticaster抽象类<code>[事件源中publishEvent方法需要调用其方法getApplicationEventMulticaster]</code></p>
<p>属于事件广播器,它的作用是把Applicationcontext发布的Event广播给所有的监听器.</p>
<p>代码：</p>
<pre><code>public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext, DisposableBean {  
    private ApplicationEventMulticaster applicationEventMulticaster;  
    protected void registerListeners() {  
    // Register statically specified listeners first.  
    for (ApplicationListener&lt;?&gt; listener : getApplicationListeners()) {  
    getApplicationEventMulticaster().addApplicationListener(listener);  
    }  
    // Do not initialize FactoryBeans here: We need to leave all regular beans  
    // uninitialized to let post-processors apply to them!  
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);  
    for (String lisName : listenerBeanNames) {  
    getApplicationEventMulticaster().addApplicationListenerBean(lisName);  
    }  
  }  
}
</code></pre><p>扩展：<a href="http://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&amp;mid=2247486897&amp;idx=2&amp;sn=927e4dd95695163fa250447ea88e12e8&amp;chksm=ebd6329ddca1bb8bebcd94bc31396ae55c6f28e0ec2057203605aedf9b8cb4a7243c1202e3c5&amp;scene=21#wechat_redirect" target="_blank" rel="noopener">设计模式是什么鬼（观察者）</a></p>
<h2 id="8-策略模式"><a href="#8-策略模式" class="headerlink" title="8.策略模式"></a>8.策略模式</h2><h3 id="实现方式：-6"><a href="#实现方式：-6" class="headerlink" title="实现方式："></a>实现方式：</h3><p>Spring框架的资源访问Resource接口。该接口提供了更强的资源访问能力，Spring 框架本身大量使用了 Resource 接口来访问底层资源。</p>
<h3 id="Resource-接口介绍"><a href="#Resource-接口介绍" class="headerlink" title="Resource 接口介绍"></a>Resource 接口介绍</h3><p>source 接口是具体资源访问策略的抽象，也是所有资源访问类所实现的接口。</p>
<p>Resource 接口主要提供了如下几个方法:</p>
<ul>
<li><p><strong>getInputStream()：</strong>定位并打开资源，返回资源对应的输入流。每次调用都返回新的输入流。调用者必须负责关闭输入流。</p>
</li>
<li><p><strong>exists()：</strong>返回 Resource 所指向的资源是否存在。</p>
</li>
<li><p><strong>isOpen()：</strong>返回资源文件是否打开，如果资源文件不能多次读取，每次读取结束应该显式关闭，以防止资源泄漏。</p>
</li>
<li><p><strong>getDescription()：</strong>返回资源的描述信息，通常用于资源处理出错时输出该信息，通常是全限定文件名或实际 URL。</p>
</li>
<li><p><strong>getFile：</strong>返回资源对应的 File 对象。</p>
</li>
<li><p><strong>getURL：</strong>返回资源对应的 URL 对象。</p>
<p>​</p>
</li>
</ul>
<p>最后两个方法通常无须使用，仅在通过简单方式访问无法实现时，Resource 提供传统的资源访问的功能。</p>
<p>Resource 接口本身没有提供访问任何底层资源的实现逻辑，<strong>针对不同的底层资源，Spring 将会提供不同的 Resource 实现类，不同的实现类负责不同的资源访问逻辑。</strong></p>
<p>Spring 为 Resource 接口提供了如下实现类：</p>
<ul>
<li style="list-style: none"><input type="checkbox" checked> <strong>UrlResource：</strong>访问网络资源的实现类。</li>
<li style="list-style: none"><input type="checkbox" checked> <strong>ClassPathResource：</strong>访问类加载路径里资源的实现类。</li>
<li style="list-style: none"><input type="checkbox" checked> <strong>FileSystemResource：</strong>访问文件系统里资源的实现类。</li>
<li style="list-style: none"><input type="checkbox" checked> <strong>ServletContextResource：</strong>访问相对于 ServletContext 路径里的资源的实现类.</li>
<li style="list-style: none"><input type="checkbox" checked> <strong>InputStreamResource：</strong>访问输入流资源的实现类。</li>
<li style="list-style: none"><input type="checkbox" checked> <strong>ByteArrayResource：</strong>访问字节数组资源的实现类。</li>
</ul>
<p>这些 Resource 实现类，针对不同的的底层资源，提供了相应的资源访问逻辑，并提供便捷的包装，以利于客户端程序的资源访问。</p>
<p>扩展：<a href="http://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&amp;mid=2247485903&amp;idx=1&amp;sn=172401bccf663455fd90c55aa957db18&amp;chksm=ebd636e3dca1bff544c671c9f8de3a6e8d40049ab7cea3d750d03ed00ef6e6c4fae376333de1&amp;scene=21#wechat_redirect" target="_blank" rel="noopener">设计模式是什么鬼（策略）</a></p>
<h2 id="9-模版方法模式"><a href="#9-模版方法模式" class="headerlink" title="9.模版方法模式"></a>9.模版方法模式</h2><h3 id="经典模板方法定义："><a href="#经典模板方法定义：" class="headerlink" title="经典模板方法定义："></a>经典模板方法定义：</h3><p>父类定义了骨架（调用哪些方法及顺序），某些特定方法由子类实现。</p>
<p>最大的好处：代码复用，减少重复代码。除了子类要实现的特定方法，其他方法及方法调用顺序都在父类中预先写好了。</p>
<p><strong>所以父类模板方法中有两类方法：</strong></p>
<p><strong>共同的方法：</strong>所有子类都会用到的代码</p>
<p><strong>不同的方法：</strong>子类要覆盖的方法，分为两种：</p>
<ol>
<li>抽象方法：父类中的是抽象方法，子类必须覆盖</li>
<li>钩子方法：父类中是一个空方法，子类继承了默认也是空的</li>
</ol>
<p>注：为什么叫钩子，子类可以通过这个钩子（方法），控制父类，因为这个钩子实际是父类的方法（空方法）！</p>
<h3 id="Spring模板方法模式实质："><a href="#Spring模板方法模式实质：" class="headerlink" title="Spring模板方法模式实质："></a>Spring模板方法模式实质：</h3><p>是模板方法模式和回调模式的结合，是Template Method不需要继承的另一种实现方式。Spring几乎所有的外接扩展都采用这种模式。</p>
<p>推荐：<a href="http://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&amp;mid=2247486148&amp;idx=1&amp;sn=601fa38aee0aa27137341ce9a2624fec&amp;chksm=ebd635e8dca1bcfe8da575478244414d13620010cd0d9823f423af8d2457ad1bb65a17d6a940&amp;scene=21#wechat_redirect" target="_blank" rel="noopener">设计模式是什么鬼（模板方法）</a></p>
<h3 id="具体实现：-1"><a href="#具体实现：-1" class="headerlink" title="具体实现："></a>具体实现：</h3><p>JDBC的抽象和对Hibernate的集成，都采用了一种理念或者处理方式，那就是模板方法模式与相应的Callback接口相结合。</p>
<p>采用模板方法模式是为了以一种统一而集中的方式来处理资源的获取和释放，以JdbcTempalte为例:</p>
<pre><code>public abstract class JdbcTemplate {  
     public final Object execute（String sql）{  
        Connection con=null;  
        Statement stmt=null;  
        try{  
            con=getConnection（）;  
            stmt=con.createStatement（）;  
            Object retValue=executeWithStatement（stmt,sql）;  
            return retValue;  
        }catch（SQLException e）{  
             ...  
        }finally{  
            closeStatement（stmt）;  
            releaseConnection（con）;  
        }  
    }   
    protected abstract Object executeWithStatement（Statement   stmt, String sql）;  
}  
</code></pre><h3 id="引入回调原因："><a href="#引入回调原因：" class="headerlink" title="引入回调原因："></a>引入回调原因：</h3><p>JdbcTemplate是抽象类，不能够独立使用，我们每次进行数据访问的时候都要给出一个相应的子类实现,这样肯定不方便，所以就引入了回调。</p>
<p>回调代码</p>
<pre><code>public interface StatementCallback{  
    Object doWithStatement（Statement stmt）;  
}   
</code></pre><p>利用回调方法重写JdbcTemplate方法</p>
<pre><code>public class JdbcTemplate {  
    public final Object execute（StatementCallback callback）{  
        Connection con=null;  
        Statement stmt=null;  
        try{  
            con=getConnection（）;  
            stmt=con.createStatement（）;  
            Object retValue=callback.doWithStatement（stmt）;  
            return retValue;  
        }catch（SQLException e）{  
            ...  
        }finally{  
            closeStatement（stmt）;  
            releaseConnection（con）;  
        }  
    }  

    ...//其它方法定义  
}   
</code></pre><p>Jdbc使用方法如下：</p>
<pre><code>JdbcTemplate jdbcTemplate=...;  
    final String sql=...;  
    StatementCallback callback=new StatementCallback(){  
    public Object=doWithStatement(Statement stmt){  
        return ...;  
    }  
}    
jdbcTemplate.execute(callback);  
</code></pre><h3 id="为什么JdbcTemplate没有使用继承？"><a href="#为什么JdbcTemplate没有使用继承？" class="headerlink" title="为什么JdbcTemplate没有使用继承？"></a>为什么JdbcTemplate没有使用继承？</h3><p>因为这个类的方法太多，但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接，那么我们怎么办呢？</p>
<p>我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码，而且这段代码会用到JdbcTemplate中的变量。怎么办？</p>
<p>那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法，我们去实现这个方法，就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate，从而完成了调用。</p>

        </div>
        <!-- .entry-content -->
        <div class="single-reward">
          <div class="reward-open">赏
            <div class="reward-main">
              <ul class="reward-row">
                <li class="alipay-code"><img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/custom/donate/AliPayQR.jpg"></li>
                <li class="wechat-code"><img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/custom/donate/WeChanQR.jpg"></li>
              </ul>
            </div>
          </div>
        </div>
        <div style="text-align:center; width: 100%" class="social-share share-mobile" data-disabled="diandian, tencent"></div>
        <footer class="post-footer">
          <div class="post-lincenses"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="nofollow"><i class="fa fa-creative-commons" aria-hidden="true"></i> 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a></div>
          <div class="post-tags">
          </div>
          <div class="post-share">
            <div class="social-share sharehidden share-component"></div>
            <i class="iconfont show-share icon-forward"></i>
          </div>
        </footer><!-- .entry-footer -->
      </article>
      <!-- #post-## -->
      <div class="toc" style="background: none;"></div>
      <section class="post-squares nextprev">
        
          
            <div class="post-nepre half previous">
          
            <a href="/2020/03/11/IDEA 的使用/" rel="prev">
              <div class="background">
                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/loader/orange.progress-bar-stripe-loader.svg" data-src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/20200322082906.png" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/20200322082906.png">
              </div>
              <span class="label">
              Previous Post</span>
              <div class="info">
                <h3>
                IDEA 的使用</h3>
                <hr>
              </div>
            </a>
          </div>
        
        
          
            <div class="post-nepre half next">
          
            <a href="/2020/03/11/三分钟快速实现二叉树的递归遍历/" rel="next">
              <div class="background">
                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/loader/orange.progress-bar-stripe-loader.svg" data-src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/asfs.gif" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/asfs.gif">
              </div>
              <span class="label">
              Next Post</span>
              <div class="info">
                <h3>
                三分钟快速实现二叉树的递归遍历</h3>
                <hr>
              </div>
            </a>
          </div>
        
      </section>
      
<div id="vcomments"></div>
<script>
  window.onload = function(){
      var valine = new Valine();
      valine.init({
        el: '#vcomments',
        appId: "aeY1WNVHlNPxnev04uP4OGiN-gzGzoHsz",
        appKey: "eC65yOIwHWdj1SI18Dc25mV2",
        path: window.location.pathname,
        placeholder: "你是我一生只会遇见一次的惊喜 ..."
      })
  }
</script>

      <section class="author-profile">
        <div class="info" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
          <a href="www.gcweb.top" class="profile gravatar"><img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/21.jpg" itemprop="image" alt="耿超" height="70" width="70"></a>
          <div class="meta">
            <span class="title">Author</span>
            <h3 itemprop="name">
            <a href="www.gcweb.top" itemprop="url" rel="author">耿超</a>
            </h3>
          </div>
        </div>
        <hr>
        <p><i class="iconfont icon-write"></i>Just Do It</p>
      </section>
    </main><!-- #main -->
  </div><!-- #primary -->
</div>



    </div>    
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="请输入关键词..."/>
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            // PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
    <!-- <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2020 耿超<br>
      powered_by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer> -->



<footer id="colophon" class="site-footer" role="contentinfo">
  <div class="site-info">
    <div class="footertext">
      <div class="img-preload">
        <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/wordpress-rotating-ball-o.svg">
        <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/disqus-preloader.svg">
      </div>
      <p style="color: #666666;">&copy 2019</p>
    </div>
    <div class="footer-device">
    <p style="font-family: 'Ubuntu', sans-serif;">
        <span style="color: #b9b9b9;">经历暴风雨后<a href="https://github.com/honjun/hexo-theme-sakura" target="_blank" style="color: #b9b9b9;;text-decoration: underline dotted rgba(0, 0, 0, .1);">.</a> <i class="iconfont icon-sakura rotating" style="color: #ffc0cb;display:inline-block"></i>终将站在最高处<a href="https://2heng.xin/" target="_blank" style="color: #b9b9b9;;text-decoration: underline dotted rgba(0, 0, 0, .1);">.</a>&✌✌✌✌<a href="https://www.hojun.cn/" target="_blank" style="color: #b9b9b9;;text-decoration: underline dotted rgba(0, 0, 0, .1);">耿超</a></a>
        </span>
      </p>
    </div>
  </div><!-- .site-info -->



    <!--新加-->
    <span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span><script>
        var now = new Date();
        function createtime() {
            var grt= new Date("06/06/2019 16:44:00");//此处修改你的建站时间或者网站上线时间
            now.setTime(now.getTime()+250);
            days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days);
            hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours);
            if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
            mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;}
            seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
            snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;}
            document.getElementById("timeDate").innerHTML = "本站虽每天被经受大量黑客攻击, 但因站长技术所向披靡, 已风雨兼程,苦苦运行 "+dnum+" 天 ";
            document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒 ！！";
            var t =document.getElementById("timeDate");
            var times =document.getElementById("times");
            t.style.color="green";
            times.style.color="green";

            /*最下面的访问人数统计的样式*/
            var pv =document.getElementById("busuanzi_container_site_pv");
            var uv =document.getElementById("busuanzi_value_site_uv");
            pv.style.right ="200px";

            uv.style.content  ="content";

        }
        setInterval("createtime()",250);</script>

</footer>



<!-- <script src="/js/tocbot.js"></script> -->
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.6/dist/jquery.fancybox.min.js"></script>


<script type="text/javascript" src="/js/lib.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script type="text/javascript" src="/js/InsightSearch.js"></script>
<script type="text/javascript" src="/js/jquery.fancybox.min.js"></script>
<script type="text/javascript" src="/js/zoom.min.js"></script>
<script type="text/javascript" src="/js/sakura-app.js"></script>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src='//unpkg.com/valine@1.3.4/dist/Valine.min.js'></script>
<script src="/js/botui.js"></script>
<!-- 不蒜子 网页计数器 -->
<script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script> -->
<script type="text/javascript">
/* <![CDATA[ */
if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
  var Poi = {"pjax":"1","movies":{"url": "https://cdn.jsdelivr.net/gh/geng-chao/sp@1.0","name":"j.mp4","live":"close"},"windowheight":"fixed","codelamp":"close","ajaxurl":"","order":"asc","formpostion":"bottom"};
} else {
  var Poi = {"pjax":"1","movies":{"url": "https://cdn.jsdelivr.net/gh/geng-chao/sp@1.0","name":"j.mp4","live":"open"},"windowheight":"auto","codelamp":"close","ajaxurl":"","order":"asc","formpostion":"bottom"};
}
/* ]]> */

</script>
<script>
$(document).ready(function() {
  if ($(".toc").length > 0 && document.body.clientWidth > 1200) {
    if ($(".pattern-center").length > 0) { //有图的情况
      tocbot.init({
          // Where to render the table of contents.
          tocSelector: '.toc', // 放置目录的容器
          // Where to grab the headings to build the table of contents.
          contentSelector: '.entry-content', // 正文内容所在
          // Which headings to grab inside of the contentSelector element.
          scrollSmooth: true,
          headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
          headingsOffset: -400,
          scrollSmoothOffset: -85
      });
    } else {
      tocbot.init({
          // Where to render the table of contents.
          tocSelector: '.toc', // 放置目录的容器
          // Where to grab the headings to build the table of contents.
          contentSelector: '.entry-content', // 正文内容所在
          // Which headings to grab inside of the contentSelector element.
          scrollSmooth: true,
          headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
          headingsOffset: -85,
          scrollSmoothOffset: -85
      });
    }
    var offsetTop = $('.toc').offset().top - 95;
    window.onscroll = function() {
      var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
      if (scrollTop >= offsetTop) {
        $('.toc').addClass('toc-fixed');
      } else {
        $('.toc').removeClass('toc-fixed');
      }
    }
  }
});
</script>


<!--底部动态字体-->
<div id="binft"></div>
<script>
    var binft = function (r) {
        function t() {
            return b[Math.floor(Math.random() * b.length)]
        }
        function e() {
            return String.fromCharCode(94 * Math.random() + 33)
        }
        function n(r) {
            for (var n = document.createDocumentFragment(), i = 0; r > i; i++) {
                var l = document.createElement("span");
                l.textContent = e(), l.style.color = t(), n.appendChild(l)
            }
            return n
        }
        function i() {
            var t = o[c.skillI];
            c.step ? c.step-- : (c.step = g, c.prefixP < l.length ? (c.prefixP >= 0 && (c.text += l[c.prefixP]), c.prefixP++) : "forward" === c.direction ? c.skillP < t.length ? (c.text += t[c.skillP], c.skillP++) : c.delay ? c.delay-- : (c.direction = "backward", c.delay = a) : c.skillP > 0 ? (c.text = c.text.slice(0, -1), c.skillP--) : (c.skillI = (c.skillI + 1) % o.length, c.direction = "forward")), r.textContent = c.text, r.appendChild(n(c.prefixP < l.length ? Math.min(s, s + c.prefixP) : Math.min(s, t.length - c.skillP))), setTimeout(i, d)
        }
        var l = "",
                o = ["碰到一点压力", "就把自己变成不堪重负的样子","碰到一点不确定性", "就把前途描慕成暗淡无光","你TM若爆了 ！","干就完了","两宫遥相望，双阙百余尺。","极宴娱心意，戚戚何所迫？"].map(function (r) {
                    return r + ""
                }),
                a = 2,
                g = 1,
                s = 5,
                d = 75,
                b = ["rgb(110,64,170)", "rgb(150,61,179)", "rgb(191,60,175)", "rgb(228,65,157)", "rgb(254,75,131)", "rgb(255,94,99)", "rgb(255,120,71)", "rgb(251,150,51)", "rgb(226,183,47)", "rgb(198,214,60)", "rgb(175,240,91)", "rgb(127,246,88)", "rgb(82,246,103)", "rgb(48,239,130)", "rgb(29,223,163)", "rgb(26,199,194)", "rgb(35,171,216)", "rgb(54,140,225)", "rgb(76,110,219)", "rgb(96,84,200)"],
                c = {
                    text: "",
                    prefixP: -s,
                    skillI: 0,
                    skillP: 0,
                    direction: "forward",
                    delay: a,
                    step: g
                };
        i()
    };
    binft(document.getElementById('binft'));
</script>


<!-- 不蒜子统计 -->
<span id="busuanzi_container_site_pv">
                本站总访问量<span id="busuanzi_value_site_pv"></span>次
        </span>
<span class="post-meta-divider">|</span>
<span id="busuanzi_container_site_uv" style='display:none'>
                本站访客数<span id="busuanzi_value_site_uv"></span>人
        </span>




    <div class="openNav no-select" style="height: 50px;">
      <div class="iconflat no-select" style="width: 50px; height: 50px;">
        <div class="icon"></div>
      </div>
      <div class="site-branding search-form-submit">
        <i class="iconfont js-toggle-search iconsearch icon-search"></i>
      </div>
    </div>
  </section>


  <!---->
  <!-- ���������������ɫ���� --><script src="https://cdn.jsdelivr.net/gh/wallleap/cdn/js/shehuizhuyi.js"></script>
  <!-- ������ְ��� --><script src="https://cdn.jsdelivr.net/gh/wallleap/cdn/js/love.js"></script>

  <script type="text/javascript">
    var windowWidth = $(window).width(); if (windowWidth > 768) { document.write('<script type="text/javascript" src="/js/sakura.js"><\/script>'); }
  </script>


  <div id="mo-nav" class="">
  <div class="m-avatar">
    <img src="https://cdn.jsdelivr.net/gh/geng-chao/PicGo/img/21.jpg">
  </div>
  <p style="text-align: center; color: #333; font-weight: 900; font-family: 'Ubuntu', sans-serif; letter-spacing: 1.5px">BigBoss耿超</p>
  <p style="text-align: center; word-spacing: 20px;">
    
      
        <a href="http://github.com/geng-chao" class="fa fa-github" target="_blank" style="color: #333; margin-left:20px"></a>
      
        <a href="http://weibo.com/mashirozx?is_all=1" class="fa fa-weibo" target="_blank" style="color: #dd4b39; margin-left:20px"></a>
      
        <a href="https://wpa.qq.com/msgrd?v=3&uin=2420479774&site=qq&menu=yes" class="fa fa-qq" target="_blank" style="color: #25c6fe; margin-left:20px"></a>
      
    
  </p>
  <ul id="menu-new-1" class="menu">
    
      <li>
        <a href="/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-fort-awesome faa-shake" aria-hidden="true"></i>
            首页
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/archives">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-archive faa-shake" aria-hidden="true"></i>
            归档
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/categories/技术/">
                  <i class="fa fa-code" aria-hidden="true"></i>
                  技术
                </a>
              </li>
            
              <li>
                <a href="/categories/生活/">
                  <i class="fa fa-file-text-o" aria-hidden="true"></i>
                  生活
                </a>
              </li>
            
              <li>
                <a href="/categories/资源/">
                  <i class="fa fa-cloud-download" aria-hidden="true"></i>
                  资源
                </a>
              </li>
            
              <li>
                <a href="/categories/java/">
                  <i class="fa fa-commenting-o" aria-hidden="true"></i>
                  java
                </a>
              </li>
            
              <li>
                <a href="/categories/转载/">
                  <i class="fa fa-book" aria-hidden="true"></i>
                  转载
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="javascript:;">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-list-ul faa-vertical" aria-hidden="true"></i>
            清单
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/tags/悦读/">
                  <i class="fa fa-th-list faa-bounce" aria-hidden="true"></i>
                  书单
                </a>
              </li>
            
              <li>
                <a href="/bangumi/">
                  <i class="fa fa-film faa-vertical" aria-hidden="true"></i>
                  番组
                </a>
              </li>
            
              <li>
                <a href="/music/">
                  <i class="fa fa-headphones" aria-hidden="true"></i>
                  歌单
                </a>
              </li>
            
              <li>
                <a href="/tags/图集/">
                  <i class="fa fa-photo" aria-hidden="true"></i>
                  图集
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/comment/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-pencil-square-o faa-tada" aria-hidden="true"></i>
            留言板
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/links/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
            友人帐
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/donate/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-heart faa-pulse" aria-hidden="true"></i>
            赞赏
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-leaf faa-wrench" aria-hidden="true"></i>
            关于
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/about/">
                  <i class="fa fa-meetup" aria-hidden="true"></i>
                  我？
                </a>
              </li>
            
              <li>
                <a href="/theme-sakura/">
                  <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                  主题
                </a>
              </li>
            
              <li>
                <a href="/lab/">
                  <i class="fa fa-cogs" aria-hidden="true"></i>
                  Lab
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/client/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-android faa-vertical" aria-hidden="true"></i>
            客户端
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/atom.xml">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-rss faa-pulse" aria-hidden="true"></i>
            RSS
          </span>
        </a>
        
      </li>
    
  </ul>
  <p style="text-align: center; font-size: 13px; color: #b9b9b9;">&copy 2019 hexo-sakura</p>
</div>
<button onclick="topFunction()" class="mobile-cd-top" id="moblieGoTop" title="Go to top" style="display: none;"><i class="fa fa-chevron-up" aria-hidden="true"></i></button>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<!-- require MetingJS -->
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>
<style>
  .aplayer .aplayer-lrc {
    height: 35px;
  }
  .aplayer .aplayer-lrc p{
    font-size: 16px;
    font-weight: 700;
    line-height: 18px !important;
  }
  .aplayer .aplayer-lrc p.aplayer-lrc-current{
    color: #FF1493;
  }
  .aplayer.aplayer-narrow .aplayer-body{
    left: -66px !important;
  }
  .aplayer.aplayer-fixed .aplayer-lrc {
    display: none;
  }
  .aplayer .aplayer-lrc.aplayer-lrc-hide {
      display:none !important;
  }
  .aplayer.aplayer-fixed .lrc-show {
    display: block;
    background: rgba(255, 255, 255, 0.8);
  }
</style>
<meting-js

    id="2660651585"

    server="netease"

    type="playlist"

    fixed="true"

    autoplay="true"

    loop="all"

    order="random"

    preload="auto"

    volume="0.7"

    mutex="true"

</meting-js>
<script>
  $(function(){
    $('body').on('click', '.aplayer', function(){
      if($('.aplayer-button').hasClass('aplayer-play')) {
        $('.aplayer-lrc').removeClass('lrc-show');
      } else {
        $('.aplayer-lrc').addClass('lrc-show');
      }
    })
  });
</script>
</body>
</html>